package pdfmerge;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;

import com.lowagie.text.Document;
import com.lowagie.text.pdf.PdfImportedPage;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfSmartCopy;

public class MergePDFFile {
	/**
	 * 合並pdf文件
	 * 
	 * @param files
	 *            要合並文件數組(絕對路徑如{ "e:\\1.pdf", "e:\\2.pdf" ,"e:\\3.pdf"}) *
	 * 
	 * @param newfile
	 *            合並後新產生的文件絕對路徑如e:\\temp.pdf
	 * 
	 * @return boolean 產生成功返回true, 否則返回false
	 */

	public static void main(String[] args) {
		/*
		 * String[] files = { "F:/Workspace/ItextPDFDemo/pdffolder/个人信用报告.pdf",
		 * "F:/Workspace/ItextPDFDemo/pdffolder/个人信用报告1.pdf",
		 * "F:/Workspace/ItextPDFDemo/pdffolder/个人信用报告2.pdf" };
		 */

		String folder = "E:/ZSLP/pdf/RELEVE_PDF";
		try {
			String[] filesInFolder = getFiles(folder);
			String savepath = "E:/ZSLP/pdf/pdfmerge.pdf";
			System.out.println("start to merge pdf file");

			mergePdfFiles(folder, filesInFolder, savepath);
			// mergePdfFilesWithMaxPage(folder, filesInFolder, savepath);
			System.out.println("merge pdf file end");

			/* PdfReader reader = new PdfReader("E:/ZSLP/pdf/RELEVE_PDF_20150630/000001_00100200600003941.pdf");
			unlockPdf(reader);
			int fileLength = reader.getFileLength();
			System.out.println(fileLength);*/
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static String[] getFiles(String folder) throws IOException {
		File _folder = new File(folder);
		String[] filesInFolder;

		if (_folder.isDirectory()) {
			filesInFolder = _folder.list();
			return filesInFolder;
		} else {
			throw new IOException("Path is not a directory");
		}
	}

	/**
	 * PDF合并，但在本机器上发现合并页数超过一定数后会报错
	 * 
	 *  使用 copy.freeReader(reader);
	 *     copy.flush()可解决上述问题
	 * 
	 * Exception in thread "main" java.lang.RuntimeException: The page 3808 was
	 * requested but the document has only 3807 pages. at
	 * com.itextpdf.text.pdf.PdfWriter.close(PdfWriter.java:1165) at
	 * com.itextpdf.text.pdf.PdfCopy.close(PdfCopy.java:486) at
	 * com.itextpdf.text.pdf.PdfDocument.close(PdfDocument.java:780) at
	 * com.itextpdf.text.pdf.PdfCopy.close(PdfCopy.java:485) at
	 * pdfmerge.MergeFile2.mergePdfFiles(MergeFile2.java:77) at
	 * pdfmerge.MergeFile2.main(MergeFile2.java:36)
	 * 
	 * @param folder
	 * @param files
	 * @param newfile
	 * @return
	 */
	public static boolean mergePdfFiles(String folder, String[] files, String newfile) {
		boolean retValue = false;
		Document document = null;
		PdfSmartCopy copy = null;
		try {
			document = new Document(
					new PdfReader(folder + File.separator + files[0]).getPageSize(1));
			copy = new PdfSmartCopy(document, new FileOutputStream(newfile));
			document.open();
			document.addAuthor("熊飞");
			for (int i = 0; i < files.length; i++) {
				PdfReader reader = new PdfReader(folder + File.separator + files[i]);
				unlockPdf(reader);
				int n = reader.getNumberOfPages();
				int fileLength = reader.getFileLength();
				for (int j = 1; j <= n; j++) {
					document.newPage();
					PdfImportedPage page = copy.getImportedPage(reader, j);
					copy.addPage(page);
				}
				// use this method to writes the reader to the document
				// and free the memory used by it
				copy.freeReader(reader);
				copy.flush();
			}
			retValue = true;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			copy.close();
			document.close();
		}
		return retValue;
	}

	/**
	 * 设定一个合并PDF文件最大页码数maxMergePage， 生成多个PDF合并文件
	 * 
	 * @param folder
	 * @param files
	 * @param newfile
	 */
	public static void mergePdfFilesWithMaxPage(String folder, String[] files, String newfile) {
		Document document = null;
		PdfSmartCopy copy = null;
		// 最大合并页码数
		int maxMergePage = 3000;
		// 已合并的pdf文件个数
		int fileCount = 0;
		// 创建的合并PDF文件总页数
		int mergePage = 0;
		// 生成文件个数，用于生成多个合并文件时命名
		int mergeFileCount = -1;
		while (true) {
			mergePage = 0;
			mergeFileCount++;
			try {
				String tempFileName = newfile;
				if (mergeFileCount > 0) {
					tempFileName = tempFileName.replace(".pdf", "_" + mergeFileCount + ".pdf");
				}
				document = new Document(
						new PdfReader(folder + File.separator + files[0]).getPageSize(1));
				copy = new PdfSmartCopy(document, new FileOutputStream(tempFileName));
				document.open();

				for (int i = fileCount; i < files.length; i++) {
					fileCount++;
					PdfReader reader = new PdfReader(folder + File.separator + files[i]);
					unlockPdf(reader);
					int n = reader.getNumberOfPages();
					for (int j = 1; j <= n; j++) {
						mergePage++;
						document.newPage();
						PdfImportedPage page = copy.getImportedPage(reader, j);
						copy.addPage(page);
					}
					copy.flush();
					if (mergePage >= maxMergePage) {
						break;
					}
				}

			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				document.close();
				copy.close();
			}
			if (fileCount == files.length) {
				break;
			}
		}
	}

	/**
	 * 对加密了的PDF进行解密
	 * @param reader
	 */
	public static void unlockPdf(PdfReader reader) {
		try {
			if (reader != null) {
				Field f = reader.getClass().getDeclaredField("encrypted");
				f.setAccessible(true);
				f.set(reader, false);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
